
#ifndef _TTG_SERVICES_LOGGER_
#define _TTG_SERVICES_LOGGER_
#include "Common/Definitions.h"

#include <stdio.h>
#include "Common/Errors.h"
#include "Runtime.Low/Services/Service.h"
#include "LoggerSettings.h"

namespace ttg
{
	namespace services
	{
		//Simple logger. It keeps information about errors and inner messages.
		//Note: it's pseudo service. It has static members and can be used from anywhere.
		class Logger :public Service
		{
			private:
				static Logger *ref;
			private:
				LoggerSettings settings;
				FILE *output;
				//Creates uninitialized logger.
				Logger();
				//Prints requred string to console.
				void printToConsole(const char *message);
				//Prints requred string to file.
				void printToFile(const char *message);
				//Prints requred string via message box.
				void showMessageBox(const char *message);
				//Creates log "record" according to filter.
				void createLogRecord(LoggerSettings::MessageFilter filter, const char *message);
			protected:
				//Service member.
				virtual void startUnSafe(std::vector<Service *> &deps, const char *params);
				//Service member.
				virtual void stopUnSafe();
			public:
				//Adds message.
				void addMessage(const char *object,
							    const char *method,
							    const char *description);
				//Adds error. Returns given Error.
				void addError(Error &error);
				void addError(const char *description);
				//Returns reference to instance (which always exists).
				inline static Logger *getRef()
				{ return ref == NULL ? (ref = new Logger()) : ref; }
				//frees logger and call close().
				virtual ~Logger();
		};

		#ifndef TTG_DEBUG
			#define addFatalError (void)
		#else
			inline void addFatalError(const char *object,
									  const char *method,
									  const char *description)
			{
				Logger::getRef()->addError(Error(Error::FATAL, object, method, description));
			}
			inline void addFatalError(const char *object,
									  const char *method,
									  const char *description1,
									  const char *description2)
			{
				Logger::getRef()->addError(Error(Error::FATAL, object, method, description1, description2));
			}

		#ifdef MICROSOFT_DIRECTX

			inline void addFatalError(const char *object,
									  const char *method,
									  const char *description,
									  HRESULT hres)
			{
				Logger::getRef()->addError(Error(Error::FATAL, object, method, description, hres));
			}
		#endif
		#endif

		#ifndef TTG_DEBUG
			#define addLocalError (void)
		#else
			inline void addLocalError(const char *object,
									  const char *method,
									  const char *description)
			{
				Logger::getRef()->addError(Error(Error::LOCAL, object, method, description));
			}

			inline void addLocalError(const char *object,
									  const char *method,
									  const char *description1,
									  const char *description2)
			{
				Logger::getRef()->addError(Error(Error::LOCAL, object, method, description1, description2));
			}
		#endif

		#ifndef TTG_DEBUG
			#define addWarning (void)
		#else
			inline void addWarning(const char *object,
								   const char *method,
								   const char *description)
			{
				Logger::getRef()->addError(Error(Error::WARNING, object, method, description));
			}
		#endif
	}
}

#endif